# coding : utf-8

import tkinter
from tkinter import ttk
from tkinter import filedialog
from tkinter import messagebox

from matplotlib.backends.backend_tkagg import (FigureCanvasTkAgg,
                                               NavigationToolbar2Tk)
# Implement the default Matplotlib key bindings.
from matplotlib.figure import Figure

from map_artist.attribute_def import (APPENDIX_ATTRIBUTE_VALUE, ROAD_AREA_VALUE)

from matplot_process import (DataProcess, DataProcSchedule, AppendixSchedule)

def rewriteRefPointsToFile(file, index):
    pass


class AppendixSaveWidget(tkinter.Toplevel):
    """
    input：appendix_id, ref_line_id
    1.选择appendix
    2.选择ref_line
    3.配置
    """
    def __init__(self, appendix_id, ref_line_id):
        super().__init__()
        self.title('设置附属物信息')
        # self.area_type = tkinter.StringVar()
        self.setupUI(appendix_id, ref_line_id)
        self.userinfo = None

    def setupUI(self, appendix_id, ref_line_id):
        row1 = tkinter.Frame(self)
        row1.pack(fill="x")
        tkinter.Label(row1, text='附属物ID：', width=12).pack(side=tkinter.LEFT)
        tkinter.Label(row1, text='{}'.format(appendix_id), width=6).pack(side=tkinter.LEFT)        
        #
        row2 = tkinter.Frame(self)
        row2.pack(fill="x")
        tkinter.Label(row2, text='车道参考系ID：', width=12).pack(side=tkinter.LEFT)
        tkinter.Label(row2, text='{}'.format(ref_line_id), width=6).pack(side=tkinter.LEFT)        
        # 第n行
        row7 = tkinter.Frame(self)
        row7.pack(fill="x")
        tkinter.Button(row7, text="取消", command=self.cancel).pack(side=tkinter.RIGHT, padx = 6, ipadx = 4)
        ok_bt = tkinter.Button(row7, text="确定", command=self.ok)
        ok_bt.pack(side=tkinter.RIGHT, ipadx = 4)
        ok_bt.focus_set()
        return

    def ok(self):
        # print(self.box['value'].index(self.box.get()))
        self.userinfo = 1
        self.destroy() # 销毁窗口
    
    def cancel(self):
        self.userinfo = None # 空！
        self.destroy()

class AppendixAttributeWidget(tkinter.Toplevel):
    """
    input：appendix_id, ref_line_id
    1.选择appendix
    2.选择ref_line
    3.配置
    """
    def __init__(self, appendix_id_list):
        super().__init__()
        self.title('设置附属物信息')
        self.area_type = tkinter.StringVar()
        self.setupUI(appendix_id_list)
    
    def setupUI(self, appendix_id_list):
        row1 = tkinter.Frame(self)
        row1.pack(fill="x")
        tkinter.Label(row1, text='附属物ID：', width=12).pack(side=tkinter.LEFT)
        tkinter.Label(row1, text='{}'.format(appendix_id_list), width=4*len(appendix_id_list)).pack(side=tkinter.LEFT)        
        #
        # row2 = tkinter.Frame(self)
        # row2.pack(fill="x")
        # tkinter.Label(row2, text='附属物ID：', width=12).pack(side=tkinter.LEFT)
        # tkinter.Label(row2, text='{}'.format(ref_line_id), width=6).pack(side=tkinter.LEFT)        
        #
        row_area_type = tkinter.Frame(self)
        row_area_type.pack(fill="x", ipadx=1, ipady=1)
        tkinter.Label(row_area_type, text='附属物属性', width=12).pack(side=tkinter.LEFT)
        box_area_type = ttk.Combobox(row_area_type, textvariable=self.area_type, width=12)
        box_area_type.pack(side=tkinter.LEFT, padx = 6)
        box_area_type['value'] = APPENDIX_ATTRIBUTE_VALUE
        box_area_type.current(1)
        self.box_area_type = box_area_type
        # 第n行
        row7 = tkinter.Frame(self)
        row7.pack(fill="x")
        tkinter.Button(row7, text="取消", command=self.cancel).pack(side=tkinter.RIGHT, padx = 6, ipadx = 4)
        ok_bt = tkinter.Button(row7, text="确定", command=self.ok)
        ok_bt.pack(side=tkinter.RIGHT, ipadx = 4)
        ok_bt.focus_set()

    def ok(self):
        # print(self.box['value'].index(self.box.get()))
        self.userinfo = [self.box_area_type['value'].index(self.box_area_type.get())] # 设置数据
        # print(self.userinfo)
        self.destroy() # 销毁窗口
    
    def cancel(self):
        self.userinfo = None # 空！
        self.destroy()

class RefLineAttributeWidget(tkinter.Toplevel):
    """
    参考线属性窗口类
    ToDo：配置一次后，记录配置好的数据，下次使用这些数据
    """
    def __init__(self, current_line_id, curv):
        super().__init__()
        self.title('设置参考线信息')        
        self.current_line_id = current_line_id
        self.speed_lower = tkinter.StringVar()
        self.speed_upper = tkinter.StringVar()
        self.height_limited = tkinter.StringVar()
        self.lanes_number = tkinter.StringVar()
        # self.traffic_direct = tkinter.StringVar()
        self.road_material = tkinter.StringVar()
        self.area_type = tkinter.StringVar()
        self.ratio = tkinter.StringVar()
        # self.userinfo = [self.speed_lower, self.speed_upper, self.lanes_number, self.traffic_direct, self.road_material]
        # self.label_text = ['速度下限', '速度上限', '车道数量', '坡度', '行车方向', '道路材料']
        # self.current_line_id = 0
        # self.speed_lower = 0
        # self.speed_upper = 0
        # self.lanes_number = 0
        # self.traffic_direct = 0
        # self.road_material = 0
       # 弹窗界面
        self.userinfo = None
        self.setupUI(curv)

    def setupRow(self, row, text, var):
        row.pack(fill="x", ipadx=1, ipady=1)
        tkinter.Label(row, text=text, width=12).pack(side=tkinter.LEFT)
        tkinter.Entry(row, textvariable=var, width=12).pack(side=tkinter.LEFT, padx = 6)

    def setupComboRow(self, row, text, var, value_list):
        pass
        row.pack(fill="x", ipadx=1, ipady=1)
        tkinter.Label(row, text=text, width=12).pack(side=tkinter.LEFT)
        box = ttk.Combobox(row, textvariable=var, width=12).pack(side=tkinter.LEFT, padx = 6)
        box['value'] = value_list

    def setupUI(self, curv):
        # 1.id
        # 2.限速
        # 3.车道数量
        # 4.行车方向
        # 8.材质
        # 第一行（两列）
        row1 = tkinter.Frame(self)
        row1.pack(fill="x")
        tkinter.Label(row1, text='参考线ID：', width=12).pack(side=tkinter.LEFT)
        self.name = tkinter.StringVar()
        tkinter.Label(row1, text='{}'.format(self.current_line_id), width=12).pack(side=tkinter.LEFT)        
        # 第二行
        row2 = tkinter.Frame(self)
        self.speed_lower.set(1)
        self.setupRow(row2, '车速下限：', self.speed_lower)
        tkinter.Label(row2, text='m/s', width=12).pack(side=tkinter.LEFT)        
        # 第三行
        row3 = tkinter.Frame(self)
        self.speed_upper.set(10)
        self.setupRow(row3, '车速上限：', self.speed_upper)
        tkinter.Label(row3, text='m/s', width=12).pack(side=tkinter.LEFT)        
        #
        row_height = tkinter.Frame(self)
        self.height_limited.set(20)
        self.setupRow(row_height, '高度限制：', self.height_limited)
        tkinter.Label(row_height, text='m', width=12).pack(side=tkinter.LEFT)        
        #
        row_curv = tkinter.Frame(self)
        row_curv.pack(fill="x")
        tkinter.Label(row_curv, text='曲率(1/m)：', width=12).pack(side=tkinter.LEFT)
        tkinter.Label(row_curv, text='{:.2f}'.format(curv), width=12).pack(side=tkinter.LEFT)        
        # 第四行
        row4 = tkinter.Frame(self)
        self.lanes_number.set(1)
        self.setupRow(row4, '车道数量：', self.lanes_number)        
        # 第四行
        row_ratio = tkinter.Frame(self)
        self.ratio.set(0)
        self.setupRow(row_ratio, '道路坡度：', self.ratio)        
        # 第五行
        row5 = tkinter.Frame(self)
        row5.pack(fill="x", ipadx=1, ipady=1)
        tkinter.Label(row5, text='行车方向', width=12).pack(side=tkinter.LEFT)
        # checkbutton0
        self.straight_value = tkinter.IntVar()
        straight_ck = tkinter.Checkbutton(row5, text='直行', variable=self.straight_value)
        straight_ck.select()
        straight_ck.pack(side=tkinter.LEFT)
        # checkbutton1
        self.left_value = tkinter.IntVar()
        left_ck = tkinter.Checkbutton(row5, text='左转', variable=self.left_value)
        left_ck.pack(side=tkinter.LEFT)
        # checkbutton2
        self.right_value = tkinter.IntVar()
        right_ck = tkinter.Checkbutton(row5, text='右转', variable=self.right_value)
        right_ck.pack(side=tkinter.LEFT)
        # checkbutton3
        self.bidirect_value = tkinter.IntVar()
        bidirect_ck = tkinter.Checkbutton(row5, text='双向', variable=self.bidirect_value)
        bidirect_ck.pack(side=tkinter.LEFT)
        # 第六行
        row6 = tkinter.Frame(self)
        row6.pack(fill="x", ipadx=1, ipady=1)
        tkinter.Label(row6, text='道路材料', width=12).pack(side=tkinter.LEFT)
        box = ttk.Combobox(row6, textvariable=self.road_material, width=12)
        box.pack(side=tkinter.LEFT, padx = 6)
        box['value'] = ['未知', '沥青', '水泥']
        box.current(1)
        self.box = box
        # 第七行
        row_area_type = tkinter.Frame(self)
        row_area_type.pack(fill="x", ipadx=1, ipady=1)
        tkinter.Label(row_area_type, text='区域属性', width=12).pack(side=tkinter.LEFT)
        box_area_type = ttk.Combobox(row_area_type, textvariable=self.area_type, width=12)
        box_area_type.pack(side=tkinter.LEFT, padx = 6)
        box_area_type['value'] = ROAD_AREA_VALUE
        box_area_type.current(1)
        self.box_area_type = box_area_type
        # 第n行
        row7 = tkinter.Frame(self)
        row7.pack(fill="x")
        tkinter.Button(row7, text="取消", command=self.cancel).pack(side=tkinter.RIGHT, padx = 6, ipadx = 4)
        ok_bt = tkinter.Button(row7, text="确定", command=self.ok)
        ok_bt.pack(side=tkinter.RIGHT, ipadx = 4)
        ok_bt.focus_set()
        pass
    
    def ok(self):
        # print(self.box['value'].index(self.box.get()))
        traffic_direct_value = [self.straight_value.get(), self.left_value.get(), self.right_value.get(), self.bidirect_value.get()]
        self.userinfo = [self.speed_lower.get(), self.speed_upper.get(), self.height_limited.get(), self.lanes_number.get(), self.ratio.get(), traffic_direct_value, self.box['value'].index(self.box.get()), self.box_area_type['value'].index(self.box_area_type.get())] # 设置数据
        self.destroy() # 销毁窗口
    
    def cancel(self):
        self.userinfo = None # 空！
        self.destroy()

class SelectLineTypeWidget(tkinter.Toplevel):
    """
    将一条线设置为参考线/边界/附属物边线 
    暂时无用
    """
    def __init__(self):
        super().__init__()        
        self.setupUI()
        self.userinfo = None


    def setupUI(self):
        self.line_type = tkinter.IntVar()
        self.line_type.set(0)
        row_select_type = tkinter.Frame(self)
        row_select_type.pack(fill="x")
        tkinter.Radiobutton(row_select_type, lable='设为参考线', variable = self.line_type, value = 0)
        tkinter.Radiobutton(row_select_type, label = '设为附属物', variable = self.line_type, value = 1)
        # 第n行
        row7 = tkinter.Frame(self)
        row7.pack(fill="x")
        tkinter.Button(row7, text="取消", command=self.cancel).pack(side=tkinter.RIGHT, padx = 6, ipadx = 4)
        ok_bt = tkinter.Button(row7, text="确定", command=self.ok)
        ok_bt.pack(side=tkinter.RIGHT, ipadx = 4)
        ok_bt.focus_set()
        pass
    
    def ok(self):
        # print(self.box['value'].index(self.box.get()))
        self.userinfo = [self.line_type.get()]
        self.destroy() # 销毁窗口
    
    def cancel(self):
        self.userinfo = None # 空！
        self.destroy()

class RefLinePointsWidget(tkinter.Toplevel):
    """
    生成车道参考点
    """
    def __init__(self, current_line_id, speed_lower, speed_upper, lanes_number, ratio):
        super().__init__()
        self.title('生成车道参考线离散点')
        self.setupUI(current_line_id, speed_lower, speed_upper, lanes_number, ratio)
        self.userinfo = None

    def setupRow(self, row, text0, width0, text1, width1):
        row.pack(fill="x", ipadx=1, ipady=1)
        tkinter.Label(row, text=text0, width=width0).pack(side=tkinter.LEFT)
        tkinter.Label(row, text=text1, width=width1).pack(side=tkinter.LEFT, padx=2)

    def setupUI(self, current_line_id, speed_lower, speed_upper, lanes_number, ratio):
        # 1.id
        # 2.限速
        # 3.车道数量
        # 4.行车方向
        # 8.材质
        # 第一行（两列）
        row1 = tkinter.Frame(self)
        row1.pack(fill="x")
        tkinter.Label(row1, text='参考线ID：', width=12).pack(side=tkinter.LEFT)
        self.name = tkinter.StringVar()
        tkinter.Label(row1, text='{}'.format(current_line_id), width=4).pack(side=tkinter.LEFT)        
        # 第二行
        row2 = tkinter.Frame(self)
        self.setupRow(row2, '车速限制：', 12, '{} - '.format(speed_lower), 2)
        self.setupRow(row2, '{}'.format(speed_upper), 2, 'm/s', 2)       
        # 第四行
        row4 = tkinter.Frame(self)
        self.setupRow(row4, '车道数量：', 12, '{}'.format(lanes_number), 2)        
        # 第四行
        row_ratio = tkinter.Frame(self)
        self.setupRow(row_ratio, '道路坡度：', 12, '{}'.format(ratio), 2)        
        # 第n行
        row7 = tkinter.Frame(self)
        row7.pack(fill="x")
        tkinter.Button(row7, text="取消", command=self.cancel).pack(side=tkinter.RIGHT, padx = 6, ipadx = 4)
        ok_bt = tkinter.Button(row7, text="确定", command=self.ok)
        ok_bt.pack(side=tkinter.RIGHT, ipadx = 4)
        ok_bt.focus_set()
        pass
    
    def ok(self):
        # print(self.box['value'].index(self.box.get()))
        self.userinfo = 1 
        self.destroy() # 销毁窗口
    
    def cancel(self):
        self.userinfo = None # 空！
        self.destroy()

class BoardAttributeWidget(tkinter.Toplevel):
    """
    车道边界线属性窗口类
    """
    def __init__(self, lanes_number, current_lanes, total_boards):
        super().__init__()
        self.title('组合车道边界线')
        self.lanes_number = lanes_number
        self.current_lanes = current_lanes
        self.total_boards = total_boards        
        # 弹窗界面
        self.setupUI()
        self.userinfo = None

    def setupUI(self):
        row1 = tkinter.Frame(self)
        row1.pack(fill="x")
        tkinter.Label(row1, text='车道数量：', width=16).pack(side=tkinter.LEFT)
        self.name = tkinter.StringVar()
        tkinter.Label(row1, text='{}'.format(self.lanes_number), width=12).pack(side=tkinter.LEFT)        

        row2 = tkinter.Frame(self)
        row2.pack(fill="x")
        tkinter.Label(row2, text='已配置边界数：', width=16).pack(side=tkinter.LEFT)
        self.name = tkinter.StringVar()
        tkinter.Label(row2, text='{}'.format(self.current_lanes), width=12).pack(side=tkinter.LEFT)        

        row3 = tkinter.Frame(self)
        row3.pack(fill="x")
        tkinter.Label(row3, text='已选择边线数：', width=16).pack(side=tkinter.LEFT)
        self.name = tkinter.StringVar()
        tkinter.Label(row3, text='{}'.format(self.total_boards), width=12).pack(side=tkinter.LEFT)        

        # 第n行
        row7 = tkinter.Frame(self)
        row7.pack(fill="x")
        tkinter.Button(row7, text="取消", command=self.cancel).pack(side=tkinter.RIGHT, padx = 6, ipadx = 4)
        ok_bt = tkinter.Button(row7, text="确定", command=self.ok)
        ok_bt.pack(side=tkinter.RIGHT, ipadx = 4)
        ok_bt.focus_set()
        pass
    
    def ok(self):
        # print(self.box['value'].index(self.box.get()))
        self.userinfo = 1 
        self.destroy() # 销毁窗口
    
    def cancel(self):
        self.userinfo = None # 空！
        self.destroy()

class ShowDataWidget(tkinter.Toplevel):
    def __init__(self, saved_line=0, bidirect_line=0, saved_length=0, total_line=0, saved_appendix=0):
        super().__init__()
        self.title('数据统计')
        # 弹窗界面
        self.setupUI(saved_line, bidirect_line, saved_length, total_line, saved_appendix)



    def setupUI(self, saved_line, bidirect_line, saved_length, total_line, saved_appendix):
        row1 = tkinter.Frame(self)
        row1.pack(fill="x")
        tkinter.Label(row1, text='已完成参考线数量：', width=16).pack(side=tkinter.LEFT)
        tkinter.Label(row1, text='{}'.format(saved_line), width=12, bg='green').pack(side=tkinter.LEFT)        

        row2 = tkinter.Frame(self)
        row2.pack(fill="x")
        tkinter.Label(row2, text='双向车道数量：', width=16).pack(side=tkinter.LEFT)
        tkinter.Label(row2, text='{}'.format(bidirect_line), width=12).pack(side=tkinter.LEFT)        

        row2 = tkinter.Frame(self)
        row2.pack(fill="x")
        tkinter.Label(row2, text='已完成参考线总长：', width=16).pack(side=tkinter.LEFT)
        tkinter.Label(row2, text='{:.2f}'.format(saved_length), width=12).pack(side=tkinter.LEFT)        

        row_nosaved = tkinter.Frame(self)
        row_nosaved.pack(fill="x")
        tkinter.Label(row_nosaved, text='未完成参考线：', width=16).pack(side=tkinter.LEFT)
        tkinter.Label(row_nosaved, text='{}'.format(total_line-saved_line), width=12).pack(side=tkinter.LEFT)        

        row3 = tkinter.Frame(self)
        row3.pack(fill="x")
        tkinter.Label(row3, text='参考线总数：', width=16).pack(side=tkinter.LEFT)
        tkinter.Label(row3, text='{}'.format(total_line), width=12).pack(side=tkinter.LEFT)        

        row4 = tkinter.Frame(self)
        row4.pack(fill="x")
        tkinter.Label(row4, text='已完成附属物：', width=16).pack(side=tkinter.LEFT)
        tkinter.Label(row4, text='{}'.format(saved_appendix), width=12).pack(side=tkinter.LEFT)        

        # 第n行
        row_button = tkinter.Frame(self)
        row_button.pack(fill="x")
        ok_bt = tkinter.Button(row_button, text="确定", command=self.ok)
        ok_bt.pack(side=tkinter.RIGHT, ipadx = 4)
        ok_bt.focus_set()
        pass
    
    def ok(self):
        self.destroy() # 销毁窗口


class checkConnectByTurnWidget(tkinter.Toplevel):
    def __init__(self, processor):
        super().__init__()
        self.current_line2d = None
        self.next_line2d_list = []
        self.title('连通图检查')
        self.connect_dict = {}
        self.connect_dict.update(processor.connect_dict)
        # 弹窗界面
        self.processor = processor

        self.checking_line_ids = sorted(list(self.connect_dict.keys())) # 
        self.checked_line_ids = list([])

        self.unsaved_line_list = []
        self.unsaved_line_index = 0
        for key in self.processor.dxfentity_dict.keys():
            if key not in self.processor.connect_dict.keys():
                self.unsaved_line_list.append(key)

        if self.checking_line_ids:
            self.checking_id = self.checking_line_ids.pop()
            self.checked_line_ids.append(self.checking_id)
        else:
            self.checking_id = None

        self.setupUI()


    def setCurrentLinesColor(self, color):
        """
        设置line2D颜色并显示
        首先将之前的‘当前车道’显示为黑色
        再根据combobox中的值，将当前车道显示为绿色
        """
        if self.current_line2d != None:
            self.current_line2d.set_color('k')
        for line in self.next_line2d_list: # 先将全部line都置为黑色
            line.set_color('k')
        self.current_line2d = None

        if self.show_saved.get() == 1:
            self.current_line2d = self.processor.ref_line2D_dict[abs(self.checking_id)]
            self.current_line2d.set_color(color)

        elif self.show_saved.get() != 1 and self.unsaved_line_list:
            unsaved_line_ID = self.unsaved_line_list[self.unsaved_line_index]
            self.current_line2d = self.processor.ref_line2D_dict[abs(unsaved_line_ID)]
            self.current_line2d.set_color(color)

        self.processor.figure.canvas.draw()
        return

    def radiobuttonPickHandle(self):
        """
        ButtonPick callback
        获取radiobutton的值，并根据值切换保存与未保存车道的显示
        只显示当前序号对应的车道
        """
        if self.show_saved.get() == 1:
            self.checking_line_ids = sorted(list(self.connect_dict.keys())) # 
            self.checked_line_ids = list([])
            if self.checking_line_ids:
                self.checking_id = self.checking_line_ids.pop()
                self.checked_line_ids.extend(self.checking_id)
            else:
                self.checking_id = None

            if self.checking_id is not None:
                self.checking_id_str.set(self.checking_id)
                self.setupCheckbuttons(self.row_next_lines, self.connect_dict[self.checking_id])
            else:
                self.checking_id_str.set('None')
                self.setupCheckbuttons(self.row_next_lines, [])
        else:
            if self.unsaved_line_list:
                self.unsaved_line_index = 0;
                self.checking_id_str.set(self.unsaved_line_list[self.unsaved_line_index])
                self.setupCheckbuttons(self.row_next_lines, [])
            else:
                self.checking_id_str.set('None')
                self.setupCheckbuttons(self.row_next_lines, [])
        self.setCurrentLinesColor('green')
        self.checkbuttonSelectHandle()
        return

    def setupCheckbuttons(self, master, next_id_list):
        for checkbutton in self.checkbutton_list:
            checkbutton.pack_forget()
        self.checkbutton_list = [] # 存储button的指针
        self.checkbutton_intvar_list = [] 
        for i, id_value in enumerate(next_id_list):
            intvar = tkinter.IntVar()
            intvar.set(id_value)
            checkbutton = tkinter.Checkbutton(master, variable = intvar, onvalue=id_value, offvalue=0, text='{}'.format(id_value), command=self.checkbuttonSelectHandle)
            checkbutton.select()
            checkbutton.pack(side=tkinter.LEFT)
            self.checkbutton_list.append(checkbutton)
            self.checkbutton_intvar_list.append(intvar)
        return

    def checkbuttonSelectHandle(self):
        for line in self.next_line2d_list:
            if line != self.current_line2d: # 先将全部line都置为黑色
                line.set_color('k')
        self.next_line2d_list = [] # 清空
        next_id_list = [] # 后续车道id
        for intvar in self.checkbutton_intvar_list:
            next_line_id = intvar.get()
            print('next_line_id={}'.format(next_line_id))
            if next_line_id != 0:
                next_id_list.append(next_line_id)
                line = self.processor.ref_line2D_dict[abs(next_line_id)]
                line.set_color('r')
                self.next_line2d_list.append(line)
        self.processor.figure.canvas.draw()

        self.connect_dict[self.checking_id] = next_id_list
        return

    def setupUI(self):
        row_saved_flag = tkinter.Frame(self)
        row_saved_flag.pack(fill="x", ipadx=1, ipady=1, pady=4)
        self.show_saved = tkinter.IntVar()
        self.show_saved.set(1)
        self.rbt_saved = tkinter.Radiobutton(row_saved_flag, text = '未完成车道', variable=self.show_saved, value = 0, command=self.radiobuttonPickHandle)
        self.rbt_saved.pack(side=tkinter.LEFT)
        rbt_unsaved = tkinter.Radiobutton(row_saved_flag, text = '已完成车道', variable=self.show_saved, value = 1, command=self.radiobuttonPickHandle)
        rbt_unsaved.pack(side=tkinter.RIGHT)

        row_current_line = tkinter.Frame(self)
        row_current_line.pack(fill="x", ipadx=1, ipady=1, pady=4)
        tkinter.Label(row_current_line, text='当前车道序号:', width=16, bg='green').pack(side=tkinter.LEFT)
        self.checking_id_str = tkinter.StringVar()
        self.checking_id_str.set(self.checking_id)
        self.box_current_line = ttk.Entry(row_current_line, width=12, textvariable=self.checking_id_str, state='readonly')
        self.box_current_line.pack(side=tkinter.LEFT, padx = 6)

        self.row_next_lines = tkinter.Frame(self)
        self.row_next_lines.pack(fill="x", pady=4)
        tkinter.Label(self.row_next_lines, text='后续车道序号:', width=16, bg='red').pack(side=tkinter.LEFT)
        self.checkbutton_list = []
        self.setupCheckbuttons(self.row_next_lines, self.connect_dict[self.checking_id])

        self.setCurrentLinesColor('green')
        self.checkbuttonSelectHandle()

        # 第n行
        row_button = tkinter.Frame(self)
        row_button.pack(fill="x", pady=4)
        pre_bt = tkinter.Button(row_button, text="<<前一条车道", command=self.commandPreLine)
        pre_bt.pack(side=tkinter.LEFT, ipadx = 4, padx = 4)

        next_bt = tkinter.Button(row_button, text="后一条车道>>", command=self.commandNextLine)
        next_bt.pack(side=tkinter.RIGHT, ipadx = 4, padx = 4)

        # ok/取消 
        row_button = tkinter.Frame(self)
        row_button.pack(fill="x", pady=4)
        ok_bt = tkinter.Button(row_button, text="确认", command=self.commandOK)
        ok_bt.pack(side=tkinter.RIGHT, ipadx = 4, padx = 4)
        ok_bt.focus_set()
        cancle_bt = tkinter.Button(row_button, text="取消", command=self.commandCancel)
        cancle_bt.pack(side=tkinter.LEFT, ipadx = 4, padx = 4)
        pass

    def commandOK(self):
        """
        保存连通图
        """
        self.current_line2d.set_color('k')
        for line in self.next_line2d_list:
            line.set_color('k')
        self.processor.figure.canvas.draw()
        self.destroy()

    def commandCancel(self):
        """
        不保存连通图
        """
        self.connect_dict = {}
        self.destroy()

    def commandPreLine(self):
        if self.show_saved.get() == 1:
            if len(self.checked_line_ids) > 1:
                print('checked_ids=', self.checked_line_ids)
                self.checked_line_ids.pop()
                self.checking_line_ids.append(self.checking_id)
                self.checking_id = self.checked_line_ids[-1]
                self.checking_id_str.set(self.checking_id)
                self.setupCheckbuttons(self.row_next_lines, self.connect_dict[self.checking_id])
        else:
            if self.unsaved_line_index > 0 and self.unsaved_line_list:
                self.unsaved_line_index -= 1
                self.checking_id_str.set(self.unsaved_line_list[self.unsaved_line_index])
                self.setupCheckbuttons(self.row_next_lines, [])
        self.setCurrentLinesColor('green')
        self.checkbuttonSelectHandle()

    def commandNextLine(self):
        if self.show_saved.get() == 1:
            if self.checking_line_ids:
                if self.connect_dict[self.checking_id]:
                    next_ids = self.connect_dict[self.checking_id]
                    index = -1
                    for next_id in next_ids:
                        if next_id in self.checking_line_ids:
                            index = self.checking_line_ids.index(next_id)
                    
                    self.checking_id = self.checking_line_ids.pop(index)
                    self.checked_line_ids.append(self.checking_id)
                else:
                    self.checking_id = self.checking_line_ids.pop()
                    self.checked_line_ids.append(self.checking_id)
            self.checking_id_str.set(self.checking_id)
            self.setupCheckbuttons(self.row_next_lines, self.connect_dict[self.checking_id])
        else:
            if self.unsaved_line_index < (len(self.unsaved_line_list)-1) and self.unsaved_line_list:
                self.unsaved_line_index += 1
                self.checking_id_str.set(self.unsaved_line_index)
                self.setupCheckbuttons(self.row_next_lines, [])
        self.setCurrentLinesColor('green')
        self.checkbuttonSelectHandle()

class checkConnectWidget(tkinter.Toplevel):
    def __init__(self, processor):
        super().__init__()
        self.current_line2d = None
        self.next_line2d_list = []
        self.title('连通图检查')
        self.connect_dict = {}
        # 弹窗界面
        self.processor = processor
        self.saved_line_list = sorted(list(self.processor.connect_dict.keys())) # 
        self.saved_line_index = 0
        self.unsaved_line_list = []
        self.unsaved_line_index = 0
        for key in self.processor.dxfentity_dict.keys():
            if key not in self.processor.connect_dict.keys():
                self.unsaved_line_list.append(key)
        self.setupUI()

    def showConnect(self, event):
        if self.show_saved.get() == 1:
            if self.saved_line_list:
                self.saved_line_index = self.box_current_line['value'].index(self.box_current_line.get()) # 获取到了值，值是connect_dict的key
                print('saved_line_index={}'.format(self.saved_line_index))
                print(self.processor.connect_dict[self.saved_line_list[self.saved_line_index]])
                # self.lable_next_lines["text"] = '{}'.format(self.processor.connect_dict[self.saved_line_list[self.saved_line_index]])
                self.setupCheckbuttons(self.row_next_lines, self.processor.connect_dict[self.saved_line_list[self.saved_line_index]])
        else:
            if self.unsaved_line_list:
                self.unsaved_line_index = self.box_current_line['value'].index(self.box_current_line.get())
                self.setupCheckbuttons(self.row_next_lines, [])
                # self.lable_next_lines["text"] = 'Unknown'
            # else:
            #     pass
        self.setCurrentLinesColor('green')
        self.checkbuttonSelectHandle()
        return

    def setCurrentLinesColor(self, color):
        """
        设置line2D颜色并显示
        首先将之前的‘当前车道’显示为黑色
        再根据combobox中的值，将当前车道显示为绿色
        """
        if self.current_line2d != None:
            self.current_line2d.set_color('k')
        for line in self.next_line2d_list: # 先将全部line都置为黑色
            line.set_color('k')
        self.current_line2d = None

        if self.show_saved.get() == 1 and self.saved_line_list:
            saved_line_ID = self.saved_line_list[self.saved_line_index]
            self.current_line2d = self.processor.ref_line2D_dict[abs(saved_line_ID)]
            self.current_line2d.set_color(color)

        elif self.show_saved.get() != 1 and self.unsaved_line_list:
            unsaved_line_ID = self.unsaved_line_list[self.unsaved_line_index]
            self.current_line2d = self.processor.ref_line2D_dict[unsaved_line_ID]
            self.current_line2d.set_color(color)

        self.processor.figure.canvas.draw()
        return

    def radiobuttonPickHandle(self):
        """
        ButtonPick callback
        获取radiobutton的值，并根据值切换保存与未保存车道的显示
        只显示当前序号对应的车道
        """
        if self.show_saved.get() == 1:
            self.box_current_line['value'] = self.saved_line_list
            if self.saved_line_list:
                self.saved_line_index = 0
                self.box_current_line.current(self.saved_line_index)
                self.box_current_line['state'] = 'enabled'
                self.setupCheckbuttons(self.row_next_lines, self.processor.connect_dict[self.saved_line_list[self.saved_line_index]])
            else:
                self.box_current_line.set('None')
                self.box_current_line['state'] = 'disabled'
                self.setupCheckbuttons(self.row_next_lines, [])
        else:
            self.box_current_line['value'] = self.unsaved_line_list
            if self.unsaved_line_list:
                self.box_current_line.current(0)
                self.box_current_line['state'] = 'enabled'
                self.setupCheckbuttons(self.row_next_lines, [])
            else:
                self.box_current_line.set('None')
                self.box_current_line['state'] = 'disabled'
                self.setupCheckbuttons(self.row_next_lines, [])
        self.setCurrentLinesColor('green')
        self.checkbuttonSelectHandle()
        return

    def getValue(self):
        """
        返回self.box_current_line中value在整个value_list中的index和具体的value
        value实际是dict的key值
        """
        key = 0
        key = self.box_current_line.get() # 获取current_line中的value，也就是dict中的key
        index = self.box_current_line['value'].index(key)
        return index, int(key)

    def setupCheckbuttons(self, master, next_id_list):
        for checkbutton in self.checkbutton_list:
            checkbutton.pack_forget()
        self.checkbutton_list = [] # 存储button的指针
        self.checkbutton_intvar_list = [] 
        for i, id_value in enumerate(next_id_list):
            intvar = tkinter.IntVar()
            intvar.set(id_value)
            checkbutton = tkinter.Checkbutton(master, variable = intvar, onvalue=id_value, offvalue=0, text='{}'.format(id_value), command=self.checkbuttonSelectHandle)
            checkbutton.select()
            checkbutton.pack(side=tkinter.LEFT)
            self.checkbutton_list.append(checkbutton)
            self.checkbutton_intvar_list.append(intvar)
        return

    def checkbuttonSelectHandle(self):
        for line in self.next_line2d_list:
            if line != self.current_line2d: # 先将全部line都置为黑色
                line.set_color('k')
        self.next_line2d_list = [] # 清空
        next_id_list = [] # 后续车道id
        for intvar in self.checkbutton_intvar_list:
            next_line_id = intvar.get()
            print('next_line_id={}'.format(next_line_id))
            if next_line_id != 0:
                next_id_list.append(next_line_id)
                line = self.processor.ref_line2D_dict[abs(next_line_id)]
                line.set_color('r')
                self.next_line2d_list.append(line)
        self.processor.figure.canvas.draw()

        current_id = self.saved_line_list[self.saved_line_index]
        self.connect_dict[current_id] = next_id_list
        # self.processor.connect_dict[self.current_line2d]
        return

    def setupUI(self):
        row_saved_flag = tkinter.Frame(self)
        row_saved_flag.pack(fill="x", ipadx=1, ipady=1, pady=4)
        self.show_saved = tkinter.IntVar()
        self.show_saved.set(1)
        self.rbt_saved = tkinter.Radiobutton(row_saved_flag, text = '未完成车道', variable=self.show_saved, value = 0, command=self.radiobuttonPickHandle)
        self.rbt_saved.pack(side=tkinter.LEFT)
        rbt_unsaved = tkinter.Radiobutton(row_saved_flag, text = '已完成车道', variable=self.show_saved, value = 1, command=self.radiobuttonPickHandle)
        rbt_unsaved.pack(side=tkinter.RIGHT)

        row_current_line = tkinter.Frame(self)
        row_current_line.pack(fill="x", ipadx=1, ipady=1, pady=4)
        tkinter.Label(row_current_line, text='当前车道序号:', width=16, bg='green').pack(side=tkinter.LEFT)
        self.box_current_line = ttk.Combobox(row_current_line, width=12)
        self.box_current_line.pack(side=tkinter.LEFT, padx = 6)
        self.box_current_line['value'] = self.saved_line_list # 默认情况为saved_line_list，key的列表
        self.box_current_line.current(self.saved_line_index)
        self.box_current_line.bind('<<ComboboxSelected>>', self.showConnect) # 下拉列表选中事件

        self.row_next_lines = tkinter.Frame(self)
        self.row_next_lines.pack(fill="x", pady=4)
        tkinter.Label(self.row_next_lines, text='后续车道序号:', width=16, bg='red').pack(side=tkinter.LEFT)
        self.checkbutton_list = []
        # self.lable_next_lines = tkinter.Label(row_next_lines, text='{}'.format(self.processor.connect_dict[self.saved_line_list[self.saved_line_index]]), width=12)
        # self.lable_next_lines.pack(side=tkinter.LEFT)     
        self.setupCheckbuttons(self.row_next_lines, self.processor.connect_dict[self.saved_line_list[self.saved_line_index]])

        self.setCurrentLinesColor('green')
        self.checkbuttonSelectHandle()

        # 第n行
        row_button = tkinter.Frame(self)
        row_button.pack(fill="x", pady=4)
        pre_bt = tkinter.Button(row_button, text="<<前一条车道", command=self.commandPreLine)
        pre_bt.pack(side=tkinter.LEFT, ipadx = 4, padx = 4)

        next_bt = tkinter.Button(row_button, text="后一条车道>>", command=self.commandNextLine)
        next_bt.pack(side=tkinter.RIGHT, ipadx = 4, padx = 4)

        # ok/取消 
        row_button = tkinter.Frame(self)
        row_button.pack(fill="x", pady=4)
        ok_bt = tkinter.Button(row_button, text="确认", command=self.commandOK)
        ok_bt.pack(side=tkinter.RIGHT, ipadx = 4, padx = 4)
        ok_bt.focus_set()
        cancle_bt = tkinter.Button(row_button, text="取消", command=self.commandCancel)
        cancle_bt.pack(side=tkinter.LEFT, ipadx = 4, padx = 4)
        pass

    def commandOK(self):
        """
        保存连通图
        """
        self.destroy()

    def commandCancel(self):
        """
        不保存连通图
        """
        self.connect_dict = {}
        self.destroy()

    def commandPreLine(self):
        if self.show_saved.get() == 1:
            if self.saved_line_index > 0  and self.saved_line_list:
                self.saved_line_index -= 1
                self.box_current_line.current(self.saved_line_index)
                self.setupCheckbuttons(self.row_next_lines, self.processor.connect_dict[self.saved_line_list[self.saved_line_index]])
        else:
            if self.unsaved_line_index > 0 and self.unsaved_line_list:
                self.unsaved_line_index -= 1
                self.box_current_line.current(self.unsaved_line_index)
                self.setupCheckbuttons(self.row_next_lines, [])
        self.setCurrentLinesColor('green')
        self.checkbuttonSelectHandle()

    def commandNextLine(self):
        if self.show_saved.get() == 1:
            if self.saved_line_index < (len(self.saved_line_list)-1)  and self.saved_line_list:
                self.saved_line_index += 1
                self.box_current_line.current(self.saved_line_index)
                # self.lable_next_lines['text'] = '{}'.format(self.processor.connect_dict[self.saved_line_list[self.saved_line_index]])
                self.setupCheckbuttons(self.row_next_lines, self.processor.connect_dict[self.saved_line_list[self.saved_line_index]])
        else:
            if self.unsaved_line_index < (len(self.unsaved_line_list)-1) and self.unsaved_line_list:
                self.unsaved_line_index += 1
                self.box_current_line.current(self.unsaved_line_index)
                self.setupCheckbuttons(self.row_next_lines, [])
        self.setCurrentLinesColor('green')
        self.checkbuttonSelectHandle()

class SelectLayerWidget(tkinter.Toplevel):
    def __init__(self, dxf_layer_list, layer_config_dict):
        super().__init__()
        self.ref_line_layer_var = []
        self.board_layer_var = []
        self.appendix_layer_var = []
        self.setupUI(dxf_layer_list, layer_config_dict)

    def setupUI(self, dxf_layer_list, layer_config_dict):
        layer_row = tkinter.Frame(self)
        layer_row.grid(column=0,row=0)

        button_row = tkinter.Frame(self)
        button_row.grid(column=0, row=1)

        ref_line_row = tkinter.Frame(layer_row)
        ref_line_row.grid(column=0, row=0)
        board_row = tkinter.Frame(layer_row)
        board_row.grid(column=1, row=0)
        appendix_row = tkinter.Frame(layer_row)
        appendix_row.grid(column=2, row=0)

        tkinter.Label(ref_line_row, text='参考线:', width=16, bg='Aqua').grid(column=0, row=0)
        for i, id_value in enumerate(dxf_layer_list):
            strvar = tkinter.StringVar()
            strvar.set(id_value)
            checkbutton = tkinter.Checkbutton(ref_line_row, variable = strvar, onvalue=id_value, offvalue=0, text='{}'.format(id_value), selectcolor='Aqua')
            if id_value in layer_config_dict['ref_line']:
                print('-----------------------', id_value)
                checkbutton.select()
            else:
                print('+++++++++++++++++++++++', id_value)
                checkbutton.deselect()
            checkbutton.grid(column=0, row=i+1, sticky=tkinter.W)
            # self.ref_line_checkbuttons.append(checkbutton)
            self.ref_line_layer_var.append(strvar)

        tkinter.Label(board_row, text='边界线:', width=16, bg='yellow').grid(column=0, row=0)
        for i, id_value in enumerate(dxf_layer_list):
            strvar = tkinter.StringVar()
            strvar.set(id_value)
            checkbutton = tkinter.Checkbutton(board_row, variable = strvar, onvalue=id_value, offvalue=0, text='{}'.format(id_value), selectcolor='yellow')
            if id_value in layer_config_dict['board']:
                checkbutton.select()
            else:
                checkbutton.deselect()
            checkbutton.grid(column=0, row=i+1, sticky=tkinter.W)
            # self.board_checkbuttons.append(checkbutton)
            self.board_layer_var.append(strvar)

        tkinter.Label(appendix_row, text='附属物:', width=16, bg='orange').grid(column=0, row=0)
        for i, id_value in enumerate(dxf_layer_list):
            strvar = tkinter.StringVar()
            strvar.set(id_value)
            checkbutton = tkinter.Checkbutton(appendix_row, variable = strvar, onvalue=id_value, offvalue=0, text='{}'.format(id_value), selectcolor='orange')
            if id_value in layer_config_dict['appendix']:
                checkbutton.select()
            else:
                checkbutton.deselect()
            checkbutton.grid(column=0, row=i+1, sticky=tkinter.W)
            # self.appendix_checkbuttons.append(checkbutton)
            self.appendix_layer_var.append(strvar)

        
        ok_bt = tkinter.Button(button_row, text="确认", command=self.commandOK, width=12, padx=4)
        ok_bt.grid(column=1, row=0, sticky=tkinter.W)
        ok_bt.focus_set()
        cancle_bt = tkinter.Button(button_row, text="取消", command=self.commandCancel, width=12, padx=4)
        cancle_bt.grid(column=0, row=0, sticky=tkinter.W)
        pass

    def commandOK(self):
        self.userinfo = {}
        self.userinfo['ref_line'] = []
        self.userinfo['board'] = []
        self.userinfo['appendix'] = []
        for var in self.ref_line_layer_var:
            if var.get() != '0':
                self.userinfo['ref_line'].append(var.get())
        
        for var in self.board_layer_var:
            if var.get() != '0':
                self.userinfo['board'].append(var.get())
        
        for var in self.appendix_layer_var:
            if var.get() != '0':
                self.userinfo['appendix'].append(var.get())
        # check
        for var in self.userinfo['ref_line']:
            if var in self.userinfo['board'] or var in self.userinfo['appendix']:
                messagebox.showerror(message='一个DXF图层不能属于多个地图图层')
                return
        for var in self.userinfo['board']:
            if var in self.userinfo['appendix']:
                messagebox.showerror(message='一个DXF图层不能属于多个地图图层')
                return
        self.destroy()

    def commandCancel(self):
        self.userinfo = {}
        self.destroy()

class CommandWidget:
    """
    右键附属物处理命令列表
    """
    def __init__(self, master, event, processor):
        self.processor = processor
        self.command = None
        self.master = master
        command_menu = tkinter.Menu(master)
        command_menu.post(event.x_root, event.y_root)

        appendix_menu = tkinter.Menu(command_menu)
        # ref_menu = tkinter.Menu(command_menu)
        
        command_menu.add_cascade(label = '附属物', menu = appendix_menu)
        appendix_menu.add_command(label = '设定附属物属性', command = self.setAppendixAttribute)
        appendix_menu.add_command(label = '选择所属车道线', command = self.setAppendixBelongings)
        appendix_menu.add_command(label = '保存配置', command = self.saveAppendixPara)
        

        # command_menu.add_cascade(label = '参考线', menu = ref_menu)
        # ref_menu.add_command(label = '设定参考线属性', command = self.setReflineAttribute)
        # ref_menu.add_command(label = '选择道路边界', command = self.selectBoardLines)
        # ref_menu.add_command(label = '生成参考点', command = self.selectBoardLines)

    def saveAppendixPara(self):
        """
        将附属物信息保存到文件
        """
        # save
        #
        self.processor.current_patches.setConfiged()
        self.processor.current_patches.clear()
        self.processor.current_patches.display()
        pass

    def setAppendixAttribute(self):
        self.processor.current_patches.setReconfig()
        self.processor.current_patches.display()
        self.processor.current_artist_command = '设定附属物属性'
        appendix_attribute_widget = AppendixAttributeWidget(self.processor.current_patches.get_urls())
        self.master.wait_window(appendix_attribute_widget)
        # self.processor.current_patches.setConfiged()
        # self.processor.current_patches.display()
        pass

    def setAppendixBelongings(self):
        self.processor.current_patches.setReconfig()
        self.processor.current_patches.display()
        self.processor.current_artist_command = '选择所属车道线'
        pass

    def setReflineAttribute(self):
        pass



class MapToolsApp:
    """
    建立一个窗口，显示plot
    """
    def __init__(self, master):
        self.master = master
        self.initMenu()
        self.figure = Figure()
        self.processor = DataProcess()
        
        mat_figure_frame = tkinter.LabelFrame(master, text='地图显示区')
        para_display_frame = tkinter.LabelFrame(master, text='地图属性区', width = 60)

        mat_figure_frame.pack(side=tkinter.LEFT, fill=tkinter.BOTH, expand=1)
        self.initFigureFrame(mat_figure_frame)

        para_display_frame.pack(side=tkinter.LEFT, fill=tkinter.BOTH, expand=0)
        self.processor.setParaFrameWindow(para_display_frame) # 将整个显示放到dataprocess中
        self.processor.initParaDisplayFrame()

    def selectLineType(self):
        info = self.getConfigure('select_line_type')
        if info is None:
            return
        else:
            # todo 完全修改模式
            pass

    # menu菜单初始化
    def initMenu(self):
        # 创建位于self.master中的menubar
        menubar = tkinter.Menu(self.master)
        # 将menubar作为master的'menu'属性
        self.master['menu'] = menubar 

        # 创建file_menu一级菜单，位于menubar
        file_menu = tkinter.Menu(menubar, tearoff = 0)
        # 利用add_cascade将file_manu添加到menubar界面
        menubar.add_cascade(label = '文件', menu = file_menu)
        # 利用add_command为file_menu添加菜单
        file_menu.add_command(label='选择DXF文件', command=self.loadDXFFile)
        file_menu.add_separator()
        file_menu.add_command(label='生成连通图', command=self.makeConnectMap)

        # 创建校验
        check_menu = tkinter.Menu(menubar, tearoff = 0)
        menubar.add_cascade(label = '校验', menu = check_menu)
        # 利用add_command为file_menu添加菜单
        check_menu.add_command(label='统计数据', command=self.showData)
        check_menu.add_separator()
        check_menu.add_command(label='检查连通图', command=self.checkConnectMap)


        # 创建关于一级菜单
        about_menu = tkinter.Menu(menubar, tearoff = 0)
        menubar.add_cascade(label = '关于', menu = about_menu)
        # 添加单选按键，是否开启提示
        self.tips_enable = tkinter.IntVar()
        self.tips_enable.set(0) # 默认关闭
        about_menu.add_checkbutton(label = '开启提示', variable = self.tips_enable, command = self.setTipsEnable)

    def showData(self):
        ShowDataWidget(self.processor.saved_road_cnt, self.processor.bidirection_road_cnt, self.processor.saved_road_length, self.processor.total_road_cnt)
        return

    def checkConnectMap(self):
        check_connect_dialog = checkConnectByTurnWidget(self.processor)
        self.master.wait_window(check_connect_dialog)
        modified_connect_dict = check_connect_dialog.connect_dict
        self.processor.connect_dict.update(modified_connect_dict)
        self.processor.saveConnectMap(self.processor.fold_dir + '_connect_map.json', self.processor.connect_dict)
        messagebox.showinfo(title='', message='连通图更新成功')
        # return

    def radioBtHandler(self):
        # self.processor.handle_ref_flag = (self.ref_line_flag.get() == 0)
        # if self.processor.handle_ref_flag:
        #     self.processor.setRefLinePicker(3)
        #     self.processor.setAppendixLinePicker(0)
        #     self.processor.current_patches.clear()
        # else:
        #     self.processor.setRefLinePicker(0)
        #     self.processor.setAppendixLinePicker(3)
        # print(self.processor.handle_ref_flag)
        return

    def setTipsEnable(self):
        self.processor.toggleTipsEnable()
        pass

    def scatterRefLine(self):
        if self.processor.getRefLinePoints(): # 参考线点生成完成
            # 开始保存数据                
            #
            messagebox.showinfo(title='成功', message='参考线生成完成')
            self.processor.resetRefLineDisplay('k')
        else:
            messagebox.showerror(title='失败', message='请确认道路边界是否正确')
            self.processor.resetRefLineDisplay('g')
        self.processor.resetBoardLinesDisplay()
        self.processor.initALineVarials()
        self.processor.setBoardLinePicker(0)
        if self.processor.handle_ref_flag:
            self.processor.setRefLinePicker(3)
            self.processor.setAppendixLinePicker(0)
        else:
            self.processor.setRefLinePicker(0)
            self.processor.setAppendixLinePicker(3)
        self.canvas.draw()
        pass

    def configRefLine(self):
        if not self.processor.handle_ref_flag:
            messagebox.showerror(title='Error Occur', message='请确认处于参考线处理模式！')
            return None
        if self.processor.schedule == DataProcSchedule.START:
            messagebox.showerror(title='Error Occur', message='请先选择一条参考线！')
            return None
        elif not self.processor.schedule == DataProcSchedule.EPS_PICKED:
            messagebox.showerror(title='Error Occur', message='请先选择参考线起点！')
            return None
        else:
            info = self.getConfigure('ref_line')
            if info is None:
                return
            else:
                self.processor.schedule = DataProcSchedule.REF_CONFIGED
                self.processor.removeLineEPs(self.figure)
                self.processor.setBoardLinePicker(3)
                pass

    def getConfigure(self, widget):
        if widget == 'ref_line':
            dxf_entity = self.processor.dxfentity_dict[self.processor.current_line_id]
            if dxf_entity.dxftype == 'LINE':
                curv = 0.0
            elif dxf_entity.dxftype == 'ARC':
                curv = 1/dxf_entity.radius
            inputDialog = RefLineAttributeWidget(self.processor.current_line_id, curv)
        elif widget == 'board':
            inputDialog = BoardAttributeWidget(self.processor.lanes_number, self.processor.current_boards_number, self.processor.current_board_line_cnt)
        # elif widget == 'appendix':
        #     inputDialog = AppendixAttributeWidget(self.processor.current_appendix_id)
        elif widget == 'save_appendix':
            inputDialog = AppendixSaveWidget(self.processor.current_appendix_id, self.processor.current_appendix_to_id)
        elif widget == 'make_ref_points':
            inputDialog = RefLinePointsWidget(self.processor.current_line_id, self.processor.speed_lower, self.processor.speed_upper, self.processor.lanes_number, self.processor.ratio)
        elif widget == 'select_line_type':
            inputDialog = SelectLineTypeWidget()
        self.master.wait_window(inputDialog) # 这一句很重要！！！        
        return inputDialog.userinfo
        
    def makeRefLinePoints(self):
        info = self.getConfigure('make_ref_points')
        if info is None:
            return
        else:
            self.scatterRefLine()
        pass

    def configBoard(self):
        if self.processor.current_board_line_cnt == 0: 
            messagebox.showerror(title='Error Occur', message='请先选择足够的道路边界！')
            return
        elif not self.processor.checkBoardLines():
            messagebox.showerror(title='Error Occur', message='每次选择一个道路边界')
            return
        else: # 每组合一次，就将boards数量加1
            info = self.getConfigure('board')
            if info is None:
                return
            else:
                # 调用processor中的方法
                board_data = []
                # 合成一个data
                for artist in self.processor.current_board_lines_list:
                    board_data.extend(artist.get_xydata())
                # 加入board list
                self.processor.current_boards_list.append(board_data)
                self.processor.current_boards_tree_list.append(spatial.KDTree(board_data))
                self.processor.current_boards_number += 1
                if self.processor.current_boards_number ==  self.processor.lanes_number + 1: # 车道边界是车道数量+1       
                    self.processor.schedule = DataProcSchedule.BOARD_PICKED
                # 清空本条车道边界
                self.processor.current_board_lines_list = []
                self.processor.current_board_line_cnt = 0
                self.canvas.draw()
                return

    def configAppendix(self):
        if self.processor.current_appendix_id == 0: 
            messagebox.showerror(title='Error Occur', message='请先选择附属物！')
            return None
        else:
            info = self.getConfigure('appendix')
            if info is None:
                return
            else:
                self.processor.appendix_dict[self.processor.current_appendix_id].type_ = info[0]
                self.processor.setAppendixLinePicker(0)
                self.processor.setRefLinePicker(3)
                self.processor.appendix_schedule = AppendixSchedule.GET_BELONG
                
    def saveAppendix(self):
        info = self.getConfigure('save_appendix')
        if info is None:
            return
        else:
            # print('save run here')
            self.processor.saveCurrentAppendixData()
            self.processor.resetAppendixLineListColor()
            self.processor.initAppendixVarials()
            self.processor.setBoardLinePicker(0)
            if self.processor.handle_ref_flag:
                self.processor.setRefLinePicker(3)
                self.processor.setAppendixLinePicker(0)
            else:
                self.processor.setRefLinePicker(0)
                self.processor.setAppendixLinePicker(3)        
            self.processor.appendix_schedule = AppendixSchedule.START
            self.canvas.draw()
        return

    # 保存现有数据
    def makeConnectMap(self):
        self.processor.makeConnectMap()
        messagebox.showinfo(title='完成', message='连通图保存成功')
        return

    def loadDXFFile(self):
        dxf_file_name = filedialog.askopenfilename(filetypes=[("DXF", '.dxf')])

        if dxf_file_name != '':
            file_fold = dxf_file_name.split('.')[0]            
            layer_config_dict = {'ref_line':[], 'board':[], 'appendix':[]}
            try: # 数据存在则读入数据
                layer_config_file = open(file_fold + '_layer_config.json', 'r')
                layer_config_lines = layer_config_file.readlines()
                for layer_config_line in layer_config_lines:
                    str_list = layer_config_line.split(',')
                    layer_config_dict[str_list[0]] = list(str_list[1:-1])
                    layer_config_dict[str_list[0]].append(str_list[-1].split('\n')[0])
                    print('xxxxx', str_list[0], 'vvvvvvvvv', layer_config_dict[str_list[0]])
                layer_config_file.close()
            except FileNotFoundError as identifier:
                layer_config_file = open(file_fold + '_layer_config.json', 'w')
                layer_config_dict = {'ref_line':[], 'board':[], 'appendix':[]}
                layer_config_file.close()
            finally:
                dxf_layer_list = self.processor.loadDXFLayer(dxf_file_name)
                select_layer_dialog = SelectLayerWidget(dxf_layer_list, layer_config_dict)
                self.master.wait_window(select_layer_dialog)
                layer_config_dict.update(select_layer_dialog.userinfo)

                layer_config_file = open(file_fold + '_layer_config.json', 'w')
                for layer_key in layer_config_dict.keys():
                    str_list = list([layer_key])
                    str_list.extend(layer_config_dict[layer_key])
                    print(str_list)
                    str_value = ','.join(str_list)
                    layer_config_file.write(str_value)
                    layer_config_file.write('\n')
                layer_config_file.close()
                pass

            self.processor.__init__()
            self.figure.clf()
            self.ax = self.figure.add_subplot(111)
            self.ax.margins(0)
            self.ax.set_aspect('equal', 'box')
            self.ax.grid(True)
            self.ax.set_title(dxf_file_name, size=12)

            self.processor.loadData(file_fold, self.figure, layer_config_dict['ref_line'], layer_config_dict['board'], layer_config_dict['appendix'])
            self.processor.setAX(self.ax)

            self.processor.setBoardLinePicker(0)
            if self.processor.handle_ref_flag:
                self.processor.setRefLinePicker(3)
                self.processor.setAppendixLinePicker(0)
            else:
                self.processor.setRefLinePicker(0)
                self.processor.setAppendixLinePicker(3)
            # and button
            self.canvas.draw()
        pass

    # matplot显示窗口
    def initFigureFrame(self, master):
        self.canvas = FigureCanvasTkAgg(self.figure, master=master)
        self.canvas.draw()
        self.canvas.get_tk_widget().pack(
            side=tkinter.LEFT, fill=tkinter.BOTH, expand=1)
        self.processor.callbackConnect(self.canvas)


if __name__ == "__main__":
    main_window = tkinter.Tk()
    main_window.title('HD Map Tools')
    # data_processor = DataProcess()
    MapToolsApp(main_window)
    main_window.mainloop()
